﻿using AForge.Controls;
using AForge.Video;
using AForge.Video.DirectShow;
using DeviceCommon;
using LogLib;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;

namespace TopCamera
{
    public class TopCamera : DeviceBase
    {
        private FilterInfoCollection videoDevices;
        private VideoCaptureDevice videoSource;
        private VideoSourcePlayer videoPlayer;
        private string _monikerString = "";
        private VideoCapabilities curVideoCapabilities;
        /// <summary>
        /// 阅读器选项
        /// </summary>
        protected TopCameraOption _option = new TopCameraOption();
        public TopCameraOption Option
        {
            get { return _option; }
            set { _option = value; }
        }

        public TopCamera()
        {
            LoadConfig();
        }

        private void LoadConfig()
        {
            if (!File.Exists(_option.ConfigFilePath))
            {
                _option.Save();
            }
            _option.Load();
            Log.WriteAsync(_option.ToString());
        }

       
        private bool GetDevices()
        {
            try
            {
                //枚举所有视频输入设备
                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                if (videoDevices.Count != 0)
                {                   
                    //@device:pnp:\\?\usb#vid_174f&pid_244c&mi_00#6&29ecd27f&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global
                    for(int i=0;i< videoDevices.Count;i++)
                    {
                        Log.WriteAsync(string.Format("当前摄像头{0}:{1}",videoDevices[i].Name,videoDevices[i].MonikerString));
                        if (!string.IsNullOrEmpty(_option.Name))
                        {
                            if(videoDevices[i].Name.ToLower()== _option.Name.ToLower())
                            {
                                _monikerString = videoDevices[i].MonikerString;
                                Log.WriteAsync("已找到视频设备1.");
                                videoSource = new VideoCaptureDevice(_monikerString);
                                return EnumeratedSupportedFrameSizes(videoSource);
                              
                            }
                        }
                        else
                        {
                            string monikerString = videoDevices[i].MonikerString;
                            if (monikerString.ToLower().Contains("pid_" + _option.Pid.ToLower()) && monikerString.ToLower().Contains("vid_" + _option.Vid.ToLower()))
                            {
                                _monikerString = monikerString;
                                Log.WriteAsync("已找到视频设备2.");
                                VideoCaptureDevice videoSourceTmp = new VideoCaptureDevice(_monikerString);
                                return EnumeratedSupportedFrameSizes(videoSourceTmp);
                            }
                        }
                                           
                    }
                }
                else
                {
                    Log.WriteAsync(string.Format("没有找到视频设备！PID[{0}],VID[{1}]", _option.Pid, _option.Vid));
                }
                return false;
            }
            catch (Exception ex)
            {
                Log.WriteAsync("error:没有找到视频设备！具体原因：" + ex.Message);
                return false;
            }
        }

        private bool EnumeratedSupportedFrameSizes(VideoCaptureDevice videoDevice)
        {
            try
            {
                 VideoCapabilities[] videoCapabilities = videoDevice.VideoCapabilities;

                foreach (VideoCapabilities capabilty in videoCapabilities)
                {
                    //cmbResolution.Items.Add(string.Format("{0} x {1}",
                     //   capabilty.FrameSize.Width, capabilty.FrameSize.Height));
                    Log.WriteAsync(string.Format("{0} x {1}", capabilty.FrameSize.Width, capabilty.FrameSize.Height));
                    if (capabilty.FrameSize.Width == _option.Width && capabilty.FrameSize.Height == _option.Height)
                    {
                        curVideoCapabilities = capabilty;
                        return true;
                    }
                }

                if (videoCapabilities.Length == 0)
                {
                    Log.WriteAsync("Not supported EnumeratedSupportedFrameSizes");
                }
                else
                {
                    Log.WriteAsync(string.Format("不支持分辨率{0}X{1}", _option.Width, _option.Height));
                }               
                //return false;
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
            return false;
        }

        //启动摄像头
        private void OpenCamera()
        {
            try 
            {
                Log.WriteAsync("开始打开摄像头");
                videoPlayer = new VideoSourcePlayer();
                isCapedPhoto = false;
                videoSource = new VideoCaptureDevice(_monikerString);
                videoSource.VideoResolution = curVideoCapabilities;
                videoPlayer.VideoSource = videoSource;
                videoPlayer.Start();
                capTime = 0;
                Log.WriteAsync("打开摄像头成功");
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
            
            //videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame); //新建事件
            //videoSource.Start();
            //videoSource.SnapshotFrame += new NewFrameEventHandler(videoSource_SnapshotFrame);
            //videoSource.
        }

        int capTime = 0;
        private string TakePhoto()
        {
            try
            {
            ReCap:
                Bitmap img = videoPlayer.GetCurrentVideoFrame();
                string saveDir = string.Format("D:\\LivePhoto\\{0}\\{1}\\", DateTime.Now.ToString("yyyy-MM"), DateTime.Now.ToString("dd"));
                if (!Directory.Exists(saveDir))
                {
                    Directory.CreateDirectory(saveDir);
                }
                string imgPath = Path.Combine(saveDir, DateTime.Now.ToString("HHmmssfff") + ".jpg");
                if (img != null)
                {
                    img.Save(imgPath, ImageFormat.Jpeg);
                    Log.WriteAsync(string.Format("拍照成功{0}", imgPath));
                }
                else   //还没有图形，摄像头可能还没启动完，等两秒，再试试
                {
                    capTime++;
                    if (capTime < 3)
                    {
                        System.Threading.Thread.Sleep(2000);
                        Log.WriteAsync(string.Format("第{0}次重拍", capTime));
                        goto ReCap;
                    }
                }                

                return imgPath.Replace('\\','#');
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
            return "";
        }

        //关闭摄像头
        private void StopCamera()
        {
            try
            {
                Log.WriteAsync("开始关闭摄像头");
                if (null != videoPlayer && videoPlayer.IsRunning)
                {
                    videoPlayer.SignalToStop();
                    videoPlayer.WaitForStop();
                }
                Log.WriteAsync("关闭摄像头成功");
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
        }

        //private string imgPath = "";
        private bool isCapedPhoto = false; 
        private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            try
            {
                if (isCapedPhoto)
                     return;
                Log.WriteAsync("取得图片");
                Bitmap bmp = (Bitmap)eventArgs.Frame.Clone();   //Clone摄像头中的一帧
                string saveDir = string.Format("D:\\LivePhoto\\{0}\\{1}\\",DateTime.Now.ToString("yyyy-MM"),DateTime.Now.ToString("dd"));
                if (!Directory.Exists(saveDir))
                {
                    Directory.CreateDirectory(saveDir);
                }
                string imgPath = Path.Combine(saveDir, DateTime.Now.ToString("HHmmssfff") + ".png");
                bmp.Save(imgPath, ImageFormat.Png);
                //如果这里不写这个，一会儿会不停的拍照，
                videoSource.NewFrame -= new NewFrameEventHandler(videoSource_NewFrame);
                Log.WriteAsync("图片保存成功:" + imgPath);
                isCapedPhoto = true;
            }
            catch(Exception ex)
            {
                Log.WriteAsync(ex.ToString());
            }
        }

        public override bool DoAction(string param, out string outParam)
        {
            outParam = "";
            Log.WriteAsync("开始拍照片");
            OpenCamera();
            TakePhoto();
            StopCamera();
            Log.WriteAsync(string.Format("结束拍照片{0}", outParam));
            return true;
        }

        public override void Exit(string inParam, out string outParam)
        {
            outParam = "";            
        }

        public override void Init(string inParam, out string outParam)
        {            
            outParam = "";
            if (GetDevices())
            {
                _bInited = true;
                string strlog = string.Format("头顶摄像头初始化成功{0}.", _monikerString);
                Log.WriteAsync(strlog);
            }
            else
            {
                _error = string.Format("头顶摄像头初始化失败。");
                Log.WriteAsync(_error);
            }
        }

        public override void ShowConfigDialog(string inParam)
        {
           
        }

        public override void Start(string inParam, out string outParam)
        {
            outParam = "";
        }

        public override void Stop(string inParam, out string outParam)
        {
            try
            {
                //StopCamera();
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
            outParam = "";           
        }
    }
}
